import gateway from "./circle-gateway.js";
import { buildUrl, getData, postData } from "./circle-common.js";

/// <reference path="./circle-types.js" />

/**
 * create wallet in cloud
 * @returns {Promise<StringResponse>} - the response
 */
export async function createWallet() {
  const path = gateway.wallet.path.createWallet;
  const url = buildUrl(path);
  return postData(url, {}, +gateway.http.timeoutWrite);
}

/**
 * list wallet addresses.
 * @returns {Promise<StringArrayResponse>} - the result.
 */
export async function listWallet() {
  const path = gateway.wallet.path.listWallet;
  const url = buildUrl(path);
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * get balance of address
 * @param {string} address - the address
 * @returns {Promise<LongResponse>} - the result.
 */
export async function getBalanceOfAddress(address) {
  const url = buildUrl(gateway.wallet.path.balanceOfAddress, { address });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} AddressAssetsInfo
 * @property {string} address - the address
 * @property {number} type - the asset type
 * @property {string} txId - transaction id
 * @property {number} idx  - the output index
 * @property {string} value - the assets value.
 * @property {string} [doubleHashHex] - the data hash hex string.
 */

/**
 * @typedef {Object} AddressAssetsInfoResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {AddressAssetsInfo[]} data - the string data.
 */

/**
 * get assets of address
 * @param {string} address - the address
 * @param {number} type - the assets type.
 * @returns {Promise<AddressAssetsInfoResponse>} - the result.
 */
export async function getAssetsOfAddress(address, type) {
  const url = buildUrl(gateway.wallet.path.assetsOfAddress, { address, type });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} AssetsInfo
 * @property {number} balance - the balance
 * @property {number} identityNum - the count of identity assets.
 * @property {number} ownershipNum - the count of ownership assets.
 * @property {number} walletNum - the count of wallets.
 */

/**
 * @typedef {Object} AssetsInfoResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {AssetsInfo} data - the assets info data.
 */

/**
 * get assets of wallet.
 * @returns {Promise<AssetsInfoResponse>} - the result.
 */
export async function getAssetsOfWallet() {
  const url = buildUrl(gateway.wallet.path.assetsOfWallet);
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} WalletSpentInfo
 * @property {string} address - the address
 * @property {number} balance - the balance
 * @property {number} spent - the spent balance.
 */

/**
 * @typedef {Object} WalletSpentInfoResponse
 * @property {number} status - the response status.
 * @property {string} message - the response message.
 * @property {WalletSpentInfo} data - the wallet spent info.
 */

/**
 * get balance of wallet.
 * @returns {Promise<WalletSpentInfoResponse>} - the result.
 */
export async function getBalanceOfWallet() {
  const url = buildUrl(gateway.wallet.path.balanceOfWallet);
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} TransactionInfo
 * @property {string} fromAddress - from address
 * @property {string} toAddress - to address
 * @property {string} txId - the transaction id
 * @property {number} idx - the output index.
 * @property {number} txType - the transaction type, 0: balance, 1: ownership, 2: identity.
 * @property {string} inOut - inOut type, IN/OUT.
 * @property {string} value - the value
 * @property {string} timestamp - the created timestamp.
 */

/**
 * @typedef {Object} TxInfoListResponse
 * @property {number} status - the response status
 * @property {string} message - the response message
 * @property {TransactionInfo[]} data - the transaction info list.
 */

/**
 * search transaction by type.
 * @param {number} type - the transaction type, 0: balance, 1: ownership, 2: identity.
 * @param {number} pageNo - the page NO.
 * @param {number} pageSize - the page Size.
 * @returns {Promise<TxInfoListResponse>} - the searched result.
 */
export async function searchTxByType(type, pageNo, pageSize) {
  const url = buildUrl(gateway.wallet.path.searchTxByType, { type, pageNo, pageSize });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * search transaction by time span.
 * @param {number} startTime - the start time in milliseconds(inclusive)
 * @param {number} endTime - the end time in milliseconds(exclusive)
 * @param {number} pageSize - the page size
 * @returns {Promise<TxInfoListResponse>} - the searched result.
 */
export async function searchTxByTime(startTime, endTime, pageSize) {
  const url = buildUrl(gateway.wallet.path.searchTxByTime, { startTime, endTime, pageSize });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * get public key hash from address
 * @param {string} address - the address.
 * @returns {Promise<StringResponse>} - the result.
 */
export async function getPubKeyHashFromAddress(address) {
  const url = buildUrl(gateway.wallet.path.getPubKeyHashFromAddress, { address });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} TransactionContentPO
 * @property {number} type - transaction type.
 * @property {string} valueHex - the value hex string.
 * @property {string} [assetsDoubleHashHex] - the asset data double hash hex string.
 */

/**
 * send assets from A to B.
 * @param {Object} input - user input.
 * @param {string} input.from - the from address
 * @param {string} [input.receivePhone] - the received phone.
 * @param {string} [input.email] - the user's email
 * @param {string} input.address - the receive address
 * @param {TransactionContentPO} input.transContent - the transaction content
 * @param {string} input.payPassword - the pay password
 * @returns {Promise<BooleanResponse>} - the sendTo result.
 */
export async function sendTo(input) {
  const url = buildUrl(gateway.wallet.path.sendTo);
  return postData(url, input, +gateway.http.timeoutWrite);
}

/**
 * pay balance from A to B.
 * @param {Object} input - user input.
 * @param {string} input.from - the from address
 * @param {string} [input.receivePhone] - the receive phone.
 * @param {string} [input.email] - the receive email.
 * @param {string} input.to  - the receive to address.
 * @param {number} input.value - the balance value.
 * @param {string} input.payPassword - the pay password.
 * @returns {Promise<BooleanResponse>} - the pay result.
 */
export async function pay(input) {
  const url = buildUrl(gateway.wallet.path.pay);
  return postData(url, input, +gateway.http.timeoutWrite);
}

/**
 * @typedef {Object} TransactionInfoResponse
 * @property {number} status - the response status.
 * @property {string} message - the response message.
 * @property {TransactionInfo} data - the transaction info data.
 */

/**
 * let me try to mine block.
 * @returns {Promise<TransactionInfoResponse>} - the result.
 */
export async function letMeTry() {
  const url = buildUrl(gateway.wallet.path.letMeTry);
  return postData(url, {}, +gateway.http.timeoutWrite);
}

/**
 * search transaction api, without user login.
 * @param {Object} input - user input
 * @param {string} input.address - the address
 * @param {string} input.inOut - the inOut flag, such as IN/OUT
 * @param {TransactionContentPO} input.transactionContent - the transaction content.
 * @returns {Promise<TxInfoListResponse>} - the search result.
 */
export async function public_searchTransaction(input) {
  const url = buildUrl(gateway.wallet.path.publicSearchTransaction);
  return postData(url, input, +gateway.http.timeoutWrite);
}

/**
 * get address list by uid.
 * @param {string} uid - the user id.
 * @returns {Promise<StringArrayResponse>} - the address list response.
 */
export async function public_getAddressByUid(uid) {
  const url = buildUrl(gateway.wallet.path.publicGetAddressByUid, { uid });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * get assets by address and type
 * @param {string} address - the user address
 * @param {number} type - the asset type, 1: ownership, 2: identity
 * @returns {Promise<AddressAssetsInfoResponse>} - the address assets info response.
 */
export async function public_getAssetsOfAddress(address, type) {
  const url = buildUrl(gateway.wallet.path.publicGetAssetsOfAddress, { address, type });
  return getData(url, +gateway.http.timeoutRead);
}

/**
 * @typedef {Object} BalanceVO
 * @property {number} confirmed - the confirmed balance.
 * @property {number} unconfirmed - the unconfirmed balance.
 */

/**
 * @typedef {Object} BalanceResponse
 * @property {number} status - the response status
 * @property {string} message - the response message.
 * @property {BalanceVO} data - the balance data.
 */

/**
 * get balance by address.
 * @param {string} address - the address.
 * @returns {Promise<BalanceResponse>} - the balance response.
 */
export async function public_getBalanceByAddress(address) {
  const url = buildUrl(gateway.wallet.path.publicGetBalanceByAddress, { address });
  return getData(url, +gateway.http.timeoutRead);
}


